/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package hybris;

import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;

/**
 *
 * @author menderleit
 */
public class FullScreen {

    private boolean quitFlag;
    private JFrame frame;
    private Window win;
    private int width;
    private int width2;
    private int height;
    private int height2;
    private int depth;
    private int refresh;
    private static BufferStrategy bs;
    private static GraphicsDevice gd;
    private static DisplayMode[] dm;
    private static GraphicsConfiguration gc;
    private static GraphicsEnvironment env;
    private static int dMode = -1;
    private int fps;
    private int frameCount;
    private long frameTimer;
    private long difTime;
    private long oldTime;
    
    public FullScreen() {
        width = 800;
        height = 800;
        depth = 32;
        refresh = 60;
        init();
    }

    public FullScreen(int width, int height) {
        this.width = width;
        this.height = height;
        this.depth = 32;
        this.refresh = 60;
        init();
    }

    public FullScreen(int width, int height, int depth) {
        this.width = width;
        this.height = height;
        this.depth = depth;
        this.refresh = 60;
        init();
    }

    public FullScreen(int width, int height, int depth, int refresh) {
        this.width = width;
        this.height = height;
        this.depth = depth;
        this.refresh = refresh;
        init();
    }

    private void init() {
        quitFlag = false;
        frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(width, height);
        frame.setLocation(0, 0);
        frame.setResizable(false);
        frame.setBackground(Color.black);
        frame.setIgnoreRepaint(true);
        frame.setVisible(true);
        frame.setFocusTraversalKeysEnabled(false);
        frame.setAlwaysOnTop(true);
        
        BufferedImage blankImg = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB);
        Cursor blankCursor = Toolkit.getDefaultToolkit().createCustomCursor(blankImg, new Point(0,0), "blank");
        
        win = new Window(frame);
        win.setFocusable(true);
        win.setFocusTraversalKeysEnabled(false);
        win.setAlwaysOnTop(true);
        win.setCursor(blankCursor);
        
        win.addKeyListener(new KeyAdapter() {

            @Override
            public void keyPressed(KeyEvent ke) {
                int key = ke.getKeyCode();
                switch (key) {
                    case KeyEvent.VK_ESCAPE:
                        quitFlag = true;
                        break;
                }
            }
        });

        // Get the default graphics device from the local graphics environment, and get a list of modes.
        env = GraphicsEnvironment.getLocalGraphicsEnvironment();
        gd = env.getDefaultScreenDevice();
        dm = gd.getDisplayModes();

        // Find the DisplayMode that we want.
        for (int i = 0; i < dm.length; i++) {
            if (dm[i].getWidth() == width && dm[i].getHeight() == height && dm[i].getBitDepth() == depth && dm[i].getRefreshRate() == refresh) {
                dMode = i;
                break;
            }
        }

        // Quit if a display mode was not found.
        if (dMode == -1) {
            quitFlag = true;
            quit();
            return;
        }

        // Add a couple of variables to easily get the center of the screen.
        width2 = width / 2;
        height2 = height / 2;

        // Set fullscreen mode and then set the resolution.
        gd.setFullScreenWindow(win);
        gd.setDisplayMode(dm[dMode]);

        // Set the front and back buffers to use Acceleration. (Not sure this works...)
        ImageCapabilities backCaps = new ImageCapabilities(true);
        ImageCapabilities frontCaps = new ImageCapabilities(true);
        BufferCapabilities bufferCaps = new BufferCapabilities(frontCaps, backCaps, BufferCapabilities.FlipContents.PRIOR);

        // Create a buffer strategy for drawing. 2 means double-buffering(2 buffers).
        try {
            win.createBufferStrategy(2, bufferCaps);
        } catch (AWTException ex) {
            Logger.getLogger(FullScreen.class.getName()).log(Level.SEVERE, null, ex);
            quitFlag = true;
            quit();
            return;
        }
        bs = win.getBufferStrategy();
        
        win.toFront();
        frameCount = 0;
        fps = 0;
        frameTimer = 0;
        oldTime = System.nanoTime() / 1000000;
    }

    // Returns a graphics object for drawing on the screen.
    public Graphics getGraphics() {
        // Update the frame-counter.
        difTime = System.nanoTime() / 1000000 - oldTime;
        oldTime = System.nanoTime() / 1000000;
        frameTimer += difTime;
        frameCount++;
        if(frameTimer >= 1000) {
            frameTimer -= 1000;
            fps = frameCount;
            frameCount = 0;
        }
        // Return the graphics object.
        return bs.getDrawGraphics();
    }

    // Copy the back-buffer to the front-buffer(the screen).
    public void show() {
        bs.show();
    }

    // Return the Frames Per Second as an int.
    public int getFPS() {
        return fps;
    }
    
    public void doQuit() {
        quitFlag = true;
    }
    
    // Returns true if we want to keep running. (if ESC was not pressed)
    public boolean getRunFlag() {
        boolean runFlag = true;
        if (quitFlag) {
            runFlag = false;
            quit();
        }
        return runFlag;
    }

    // Get the width of the screen.
    public int getWidth() {
        return width;
    }

    // Get the height of the screen.
    public int getHeight() {
        return height;
    }

    // Get the center of the screen on the horizontal axis.
    public int getWidth2() {
        return width2;
    }

    // Get the center of the screen on the vertical axis.
    public int getHeight2() {
        return height2;
    }

    // Get the window we are using.
    public Window getWindow() {
        return win;
    }
    
    // Quit fullscreen mode.
    private void quit() {
        gd.setFullScreenWindow(null);
        bs.dispose();
        win.dispose();
        frame.dispose();
    }
}
